#include "sdio_sdcard.h"
#include "string.h"   
#include "usart.h"   
    

static u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1;    //SD卡类型（默认为1.x卡）
static u32 CSD_Tab[4],CID_Tab[4],RCA=0;          //SD卡CSD,CID以及相对地址(RCA)数据
static u8 DeviceMode=SD_DMA_MODE;               //工作模式,注意,工作模式必须通过SD_SetDeviceMode,后才算数.这里只是定义一个默认的模式(SD_DMA_MODE)
static u8 StopCondition=0;                 //是否发送停止传输标志位,DMA多块读写的时候用到  
volatile SD_Error TransferError=SD_OK;          //数据传输错误标志,DMA读写时使用      
volatile u8 TransferEnd=0;                //传输结束标志,DMA读写时使用
SD_CardInfo SDCardInfo;                  //SD卡信息

//SD_ReadDisk/SD_WriteDisk函数专用buf,当这两个函数的数据缓存区地址不是4字节对齐的时候,
//需要用到该数组,确保数据缓存区地址是4字节对齐的.
__align(4) u8 SDIO_DATA_BUFFER[512];              

//初始化SD卡
//返回值:错误代码;(0,无错误)
SD_Error SD_Init(void)
{
    u8 clkdiv=0;
    SD_Error errorstatus=SD_OK;     
    //! SDIO IO口初始化
    RCC->APB2ENR|=1<<4;      //使能PORTC时钟        
    RCC->APB2ENR|=1<<5;      //使能PORTD时钟
    RCC->AHBENR|=1<<10;      //使能SDIO时钟        
     RCC->AHBENR|=1<<1;      //使能DMA2时钟

    GPIOC->CRH&=0XFFF00000; 
    GPIOC->CRH|=0X000BBBBB;  //PC.8~12 复用输出
    GPIOD->CRL&=0XFFFFF0FF; 
    GPIOD->CRL|=0X00000B00;  //PD2复用输出
  
     //SDIO外设寄存器设置为默认值          
    SDIO->POWER=0x00000000;
    SDIO->CLKCR=0x00000000;
    SDIO->ARG=0x00000000;
    SDIO->CMD=0x00000000;
    SDIO->DTIMER=0x00000000;
    SDIO->DLEN=0x00000000;
    SDIO->DCTRL=0x00000000;
    SDIO->ICR=0x00C007FF;
    SDIO->MASK=0x00000000;    
    
     NVIC_Set_IRQn(SDIO_IRQn , 0x1F) ;
     errorstatus=SD_PowerON();      //SD卡上电
     if(errorstatus==SD_OK)errorstatus=SD_InitializeCards();      //初始化SD卡                              
    if(errorstatus==SD_OK)errorstatus=SD_GetCardInfo(&SDCardInfo);  //获取卡信息
     if(errorstatus==SD_OK)errorstatus=SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡   
     if(errorstatus==SD_OK)errorstatus=SD_EnableWideBusOperation(1);  //4位宽度,如果是MMC卡,则不能用4位模式 
    if((errorstatus==SD_OK)||(SDIO_MULTIMEDIA_CARD==CardType))
    {          
        if(SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0)
        {
            clkdiv=SDIO_TRANSFER_CLK_DIV+6;  //V1.1/V2.0卡，设置最高72/12=6Mhz
        }else clkdiv=SDIO_TRANSFER_CLK_DIV;  //SDHC等其他卡，设置最高72/6=12Mhz
        
        SDIO_Clock_Set(clkdiv);        //设置时钟频率,SDIO时钟计算公式:SDIO_CK时钟=SDIOCLK/[clkdiv+2];其中,SDIOCLK固定为48Mhz 
        //errorstatus=SD_SetDeviceMode(SD_DMA_MODE);  //设置为DMA模式
        errorstatus=SD_SetDeviceMode(SD_POLLING_MODE);  //设置为查询模式
     }
    return errorstatus;     
}
//SDIO时钟初始化设置
//clkdiv:时钟分频系数
//CK时钟=SDIOCLK/[clkdiv+2];(SDIOCLK时钟固定为48Mhz)
void SDIO_Clock_Set(u8 clkdiv)
{
  u32 tmpreg=SDIO->CLKCR; 
    tmpreg&=0XFFFFFF00; 
   tmpreg|=clkdiv;   
  SDIO->CLKCR=tmpreg;
} 
//SDIO发送命令函数
//cmdindex:命令索引,低六位有效
//waitrsp:期待的相应.00/10,无响应;01,短响应;11,长响应
//arg:参数
void SDIO_Send_Cmd(u8 cmdindex,u8 waitrsp,u32 arg)
{      
  u32 tmpreg;
  SDIO->ARG=arg;
  tmpreg=SDIO->CMD; 
  tmpreg&=0XFFFFF800;    //清除index和waitrsp
  tmpreg|=cmdindex&0X3F;  //设置新的index       
  tmpreg|=waitrsp<<6;    //设置新的wait rsp 
  tmpreg|=0<<8;      //无等待
    tmpreg|=1<<10;      //命令通道状态机使能
  SDIO->CMD=tmpreg;
}
//SDIO发送数据配置函数
//datatimeout:超时时间设置
//datalen:传输数据长度,低25位有效,必须为块大小的整数倍
//blksize:块大小.实际大小为:2^blksize字节
//dir:数据传输方向:0,控制器到卡;1,卡到控制器;
void SDIO_Send_Data_Cfg(u32 datatimeout,u32 datalen,u8 blksize,u8 dir)
{
  u32 tmpreg;
  SDIO->DTIMER=datatimeout;
    SDIO->DLEN=datalen&0X1FFFFFF;  //低25位有效
  tmpreg=SDIO->DCTRL; 
  tmpreg&=0xFFFFFF08;    //清除之前的设置.
  tmpreg|=blksize<<4;    //设置块大小
  tmpreg|=0<<2;      //块数据传输
  tmpreg|=(dir&0X01)<<1;  //方向控制
  tmpreg|=1<<0;      //数据传输使能,DPSM状态机
  SDIO->DCTRL=tmpreg;    
}  

//卡上电
//查询所有SDIO接口上的卡设备,并查询其电压和配置时钟
//返回值:错误代码;(0,无错误)
SD_Error SD_PowerON(void)
{
   u8 i=0;
  SD_Error errorstatus=SD_OK;
  u32 response=0,count=0,validvoltage=0;
  u32 SDType=SD_STD_CAPACITY;
  //配置CLKCR寄存器 
  SDIO->CLKCR=0;        //清空CLKCR之前的设置
  SDIO->CLKCR|=0<<9;      //非省电模式
  SDIO->CLKCR|=0<<10;      //关闭旁路,CK根据分频设置输出
  SDIO->CLKCR|=0<<11;      //1位数据宽度
  SDIO->CLKCR|=0<<13;      //SDIOCLK上升沿产生SDIOCK
  SDIO->CLKCR|=0<<14;      //关闭硬件流控制    
  SDIO_Clock_Set(SDIO_INIT_CLK_DIV);//设置时钟频率(初始化的时候,不能超过400Khz)       
   SDIO->POWER=0X03;      //上电状态,开启卡时钟    
    SDIO->CLKCR|=1<<8;      //SDIOCK使能   
     for(i=0;i<74;i++)
  {
    SDIO_Send_Cmd(SD_CMD_GO_IDLE_STATE,0,0);//发送CMD0进入IDLE STAGE模式命令.                          
    errorstatus=CmdError();
    if(errorstatus==SD_OK)break;
   }
   if(errorstatus)return errorstatus;//返回错误状态
  SDIO_Send_Cmd(SDIO_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性.
                             //arg[11:8]:01,支持电压范围,2.7~3.6V
                            //arg[7:0]:默认0XAA
                            //返回响应7
    errorstatus=CmdResp7Error();            //等待R7响应
   if(errorstatus==SD_OK)                 //R7响应正常
  {
    CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0;    //SD 2.0卡
    SDType=SD_HIGH_CAPACITY;               //高容量卡
  }
  SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0);          //发送CMD55,短响应   
  errorstatus=CmdResp1Error(SD_CMD_APP_CMD);        //等待R1响应   
  if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
  {                                  
    //SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 
    while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
    {                            
      SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0);        //发送CMD55,短响应   
      errorstatus=CmdResp1Error(SD_CMD_APP_CMD);      //等待R1响应   
       if(errorstatus!=SD_OK)return errorstatus;     //响应错误
      SDIO_Send_Cmd(SD_CMD_SD_APP_OP_COND,1,SD_VOLTAGE_WINDOW_SD|SDType);//发送ACMD41,短响应   
      errorstatus=CmdResp3Error();           //等待R3响应   
       if(errorstatus!=SD_OK)return errorstatus;     //响应错误  
      response=SDIO->RESP1;;                 //得到响应
      validvoltage=(((response>>31)==1)?1:0);      //判断SD卡上电是否完成
      count++;
    }
    if(count>=SD_MAX_VOLT_TRIAL)
    {
      errorstatus=SD_INVALID_VOLTRANGE;
      return errorstatus;
    }   
    if(response&=SD_HIGH_CAPACITY)
    {
      CardType=SDIO_HIGH_CAPACITY_SD_CARD;
    }
   }else//MMC卡
  {
    //MMC卡,发送CMD1 SDIO_SEND_OP_COND,参数为:0x80FF8000 
    while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
    {                                       
      SDIO_Send_Cmd(SD_CMD_SEND_OP_COND,1,SD_VOLTAGE_WINDOW_MMC);//发送CMD1,短响应   
      errorstatus=CmdResp3Error();           //等待R3响应   
       if(errorstatus!=SD_OK)return errorstatus;     //响应错误  
      response=SDIO->RESP1;;                 //得到响应
      validvoltage=(((response>>31)==1)?1:0);
      count++;
    }
    if(count>=SD_MAX_VOLT_TRIAL)
    {
      errorstatus=SD_INVALID_VOLTRANGE;
      return errorstatus;
    }             
    CardType=SDIO_MULTIMEDIA_CARD;    
    }  
    return(errorstatus);    
}
//SD卡 Power OFF
//返回值:错误代码;(0,无错误)
SD_Error SD_PowerOFF(void)
{
    SDIO->POWER&=~(3<<0);//SDIO电源关闭,时钟停止  
  return SD_OK;      
}   
//初始化所有的卡,并让卡进入就绪状态
//返回值:错误代码
SD_Error SD_InitializeCards(void)
{
   SD_Error errorstatus=SD_OK;
  u16 rca = 0x01;
   if((SDIO->POWER&0X03)==0)return SD_REQUEST_NOT_APPLICABLE;//检查电源状态,确保为上电状态
   if(SDIO_SECURE_DIGITAL_IO_CARD!=CardType)      //非SECURE_DIGITAL_IO_CARD
  {
    SDIO_Send_Cmd(SD_CMD_ALL_SEND_CID,3,0);      //发送CMD2,取得CID,长响应   
    errorstatus=CmdResp2Error();           //等待R2响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误        
     CID_Tab[0]=SDIO->RESP1;
    CID_Tab[1]=SDIO->RESP2;
    CID_Tab[2]=SDIO->RESP3;
    CID_Tab[3]=SDIO->RESP4;
  }
  if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_SECURE_DIGITAL_IO_COMBO_CARD==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))//判断卡类型
  {
    SDIO_Send_Cmd(SD_CMD_SET_REL_ADDR,1,0);      //发送CMD3,短响应 
    errorstatus=CmdResp6Error(SD_CMD_SET_REL_ADDR,&rca);//等待R6响应 
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误        
  }   
    if (SDIO_MULTIMEDIA_CARD==CardType)
    {
     SDIO_Send_Cmd(SD_CMD_SET_REL_ADDR,1,(u32)(rca<<16));//发送CMD3,短响应      
    errorstatus=CmdResp2Error();           //等待R2响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误   
    }
  if (SDIO_SECURE_DIGITAL_IO_CARD!=CardType)      //非SECURE_DIGITAL_IO_CARD
  {
    RCA = rca;
    SDIO_Send_Cmd(SD_CMD_SEND_CSD,3,(u32)(rca<<16));//发送CMD9+卡RCA,取得CSD,长响应      
    errorstatus=CmdResp2Error();           //等待R2响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误        
      CSD_Tab[0]=SDIO->RESP1;
    CSD_Tab[1]=SDIO->RESP2;
    CSD_Tab[2]=SDIO->RESP3;            
    CSD_Tab[3]=SDIO->RESP4;              
  }
  return SD_OK;//卡初始化成功
} 
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
   SD_Error errorstatus=SD_OK;
  u8 tmp=0;     
  cardinfo->CardType=(u8)CardType;         //卡类型
  cardinfo->RCA=(u16)RCA;              //卡RCA值
  tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
  cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6;    //CSD结构
  cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2;  //2.0协议还没定义这部分(为保留),应该是后续协议定义的
  cardinfo->SD_csd.Reserved1=tmp&0x03;      //2个保留位  
  tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16);      //第1个字节
  cardinfo->SD_csd.TAAC=tmp;               //数据读时间1
  tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8);        //第2个字节
  cardinfo->SD_csd.NSAC=tmp;              //数据读时间2
  tmp=(u8)(CSD_Tab[0]&0x000000FF);        //第3个字节
  cardinfo->SD_csd.MaxBusClkFrec=tmp;          //传输速度     
  tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24);      //第4个字节
  cardinfo->SD_csd.CardComdClasses=tmp<<4;      //卡指令类高四位
  tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16);       //第5个字节
  cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
  cardinfo->SD_csd.RdBlockLen=tmp&0x0F;        //最大读取数据长度
  tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8);      //第6个字节
  cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7;  //允许分块读
  cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6;  //写块错位
  cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5;  //读块错位
  cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
  cardinfo->SD_csd.Reserved2=0;           //保留
   if((CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1)||(CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0)||(SDIO_MULTIMEDIA_CARD==CardType))//标准1.1/2.0卡/MMC卡
  {
    cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10;  //C_SIZE(12位)
     tmp=(u8)(CSD_Tab[1]&0x000000FF);       //第7个字节  
    cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
     tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);    //第8个字节  
    cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
     cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
    cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
     tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);    //第9个字节  
    cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
    cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
    cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
     tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);      //第10个字节  
    cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
     cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
    cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
    cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
    cardinfo->CardCapacity*=cardinfo->CardBlockSize;
  }else if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)  //高容量卡
  {
     tmp=(u8)(CSD_Tab[1]&0x000000FF);     //第7个字节  
    cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
     tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);   //第8个字节  
     cardinfo->SD_csd.DeviceSize|=(tmp<<8);
     tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);  //第9个字节  
     cardinfo->SD_csd.DeviceSize|=(tmp);
     tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);   //第10个字节  
     cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
    cardinfo->CardBlockSize=512;       //块大小固定为512字节
  }    
  cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
  cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;     
  tmp=(u8)(CSD_Tab[2]&0x000000FF);      //第11个字节  
  cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
  cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
   tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24);    //第12个字节  
  cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
  cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
  cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
  cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;   
  tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16);    //第13个字节
  cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
  cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
  cardinfo->SD_csd.Reserved3=0;
  cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  
  tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8);    //第14个字节
  cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
  cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
  cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
  cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
  cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
  cardinfo->SD_csd.ECC=(tmp&0x03);  
  tmp=(u8)(CSD_Tab[3]&0x000000FF);      //第15个字节
  cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
  cardinfo->SD_csd.Reserved4=1;     
  tmp=(u8)((CID_Tab[0]&0xFF000000)>>24);    //第0个字节
  cardinfo->SD_cid.ManufacturerID=tmp;        
  tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16);    //第1个字节
  cardinfo->SD_cid.OEM_AppliID=tmp<<8;    
  tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8);    //第2个字节
  cardinfo->SD_cid.OEM_AppliID|=tmp;      
  tmp=(u8)(CID_Tab[0]&0x000000FF);      //第3个字节  
  cardinfo->SD_cid.ProdName1=tmp<<24;          
  tmp=(u8)((CID_Tab[1]&0xFF000000)>>24);     //第4个字节
  cardinfo->SD_cid.ProdName1|=tmp<<16;    
  tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16);       //第5个字节
  cardinfo->SD_cid.ProdName1|=tmp<<8;     
  tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8);    //第6个字节
  cardinfo->SD_cid.ProdName1|=tmp;       
  tmp=(u8)(CID_Tab[1]&0x000000FF);        //第7个字节
  cardinfo->SD_cid.ProdName2=tmp;        
  tmp=(u8)((CID_Tab[2]&0xFF000000)>>24);     //第8个字节
  cardinfo->SD_cid.ProdRev=tmp;     
  tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16);    //第9个字节
  cardinfo->SD_cid.ProdSN=tmp<<24;     
  tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8);     //第10个字节
  cardinfo->SD_cid.ProdSN|=tmp<<16;     
  tmp=(u8)(CID_Tab[2]&0x000000FF);         //第11个字节
  cardinfo->SD_cid.ProdSN|=tmp<<8;       
  tmp=(u8)((CID_Tab[3]&0xFF000000)>>24);     //第12个字节
  cardinfo->SD_cid.ProdSN|=tmp;           
  tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16);     //第13个字节
  cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
  cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;    
  tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8);    //第14个字节
  cardinfo->SD_cid.ManufactDate|=tmp;         
  tmp=(u8)(CID_Tab[3]&0x000000FF);      //第15个字节
  cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
  cardinfo->SD_cid.Reserved2=1;   
  return errorstatus;
}
//设置SDIO总线宽度(MMC卡不支持4bit模式)
//wmode:位宽模式.0,1位数据宽度;1,4位数据宽度;2,8位数据宽度
//返回值:SD卡错误状态
SD_Error SD_EnableWideBusOperation(u32 wmode)
{
    SD_Error errorstatus=SD_OK;
   if(SDIO_MULTIMEDIA_CARD==CardType)return SD_UNSUPPORTED_FEATURE;//MMC卡不支持
   else if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))
  {
    if(wmode>=2)return SD_UNSUPPORTED_FEATURE;//不支持8位模式
     else   
    {
      errorstatus=SDEnWideBus(wmode);
       if(SD_OK==errorstatus)
      {
        SDIO->CLKCR&=~(3<<11);    //清除之前的位宽设置    
        SDIO->CLKCR|=(u16)wmode<<11;//1位/4位总线宽度 
        SDIO->CLKCR|=0<<14;      //不开启硬件流控制
      }
    }  
  }
  return errorstatus; 
}
//设置SD卡工作模式
//Mode:
//返回值:错误状态
SD_Error SD_SetDeviceMode(u32 Mode)
{
  SD_Error errorstatus = SD_OK;
   if((Mode==SD_DMA_MODE)||(Mode==SD_POLLING_MODE))DeviceMode=Mode;
  else errorstatus=SD_INVALID_PARAMETER;
  return errorstatus;      
}
//选卡
//发送CMD7,选择相对地址(rca)为addr的卡,取消其他卡.如果为0,则都不选择.
//addr:卡的RCA地址
SD_Error SD_SelectDeselect(u32 addr)
{
   SDIO_Send_Cmd(SD_CMD_SEL_DESEL_CARD,1,addr);  //发送CMD7,选择卡,短响应        
     return CmdResp1Error(SD_CMD_SEL_DESEL_CARD);    
}
//SD卡读取一个块 
//buf:读数据缓存区(必须4字节对齐!!)
//addr:读取地址
//blksize:块大小
SD_Error SD_ReadBlock(u8 *buf,long long addr,u16 blksize)
{    
  SD_Error errorstatus=SD_OK;
  u8 power;
     u32 count=0,*tempbuff=(u32*)buf;//转换为u32指针 
  u32 timeout=SDIO_DATATIMEOUT;   
     if(NULL==buf)return SD_INVALID_PARAMETER; 
     SDIO->DCTRL=0x0;  //数据控制寄存器清零(关DMA)   
  if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)//大容量卡
  {
    blksize=512;
    addr>>=9;
  }   
    SDIO_Send_Data_Cfg(SD_DATATIMEOUT,0,0,0);  //清除DPSM状态机配置
  if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
  if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
  {
    power=convert_from_bytes_to_power_of_two(blksize);           
    SDIO_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);  //发送CMD16+设置数据长度为blksize,短响应      
    errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);  //等待R1响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误   
  }else return SD_INVALID_PARAMETER;                              
    SDIO_Send_Data_Cfg(SD_DATATIMEOUT,blksize,power,1);  //blksize,卡到控制器    
     SDIO_Send_Cmd(SD_CMD_READ_SINGLE_BLOCK,1,addr);    //发送CMD17+从addr地址出读取数据,短响应      
  errorstatus=CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);//等待R1响应   
  if(errorstatus!=SD_OK)return errorstatus;       //响应错误   
   if(DeviceMode==SD_POLLING_MODE)            //查询模式,轮询数据   
  {
//     INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
    while(!(SDIO->STA&((1<<5)|(1<<1)|(1<<3)|(1<<10)|(1<<9))))//无上溢/CRC/超时/完成(标志)/起始位错误
    {
      if(SDIO->STA&(1<<15))            //接收区半满,表示至少存了8个字
      {
        for(count=0;count<8;count++)      //循环读取数据
        {
          *(tempbuff+count)=SDIO->FIFO;
        }
        tempbuff+=8;   
        timeout=0X7FFFFF;   //读数据溢出时间
      }else   //处理超时
      {
        if(timeout==0)return SD_DATA_TIMEOUT;
        timeout--;
      }
    } 
    if(SDIO->STA&(1<<3))    //数据超时错误
    {                       
       SDIO->ICR|=1<<3;     //清错误标志
      return SD_DATA_TIMEOUT;
     }else if(SDIO->STA&(1<<1))  //数据块CRC错误
    {
       SDIO->ICR|=1<<1;     //清错误标志
      return SD_DATA_CRC_FAIL;       
    }else if(SDIO->STA&(1<<5))   //接收fifo上溢错误
    {
       SDIO->ICR|=1<<5;     //清错误标志
      return SD_RX_OVERRUN;     
    }else if(SDIO->STA&(1<<9))   //接收起始位错误
    {
       SDIO->ICR|=1<<9;     //清错误标志
      return SD_START_BIT_ERR;     
    }   
    while(SDIO->STA&(1<<21))  //FIFO里面,还存在可用数据
    {
      *tempbuff=SDIO->FIFO;  //循环读取数据
      tempbuff++;
    }
//    INTX_ENABLE();//开启总中断
    SDIO->ICR=0X5FF;       //清除所有标记
  }else if(DeviceMode==SD_DMA_MODE)
  {
        SD_DMA_Config((u32*)buf,blksize,0); 
    TransferError=SD_OK;
    StopCondition=0;      //单块读,不需要发送停止传输指令
    TransferEnd=0;        //传输结束标置位，在中断服务置1
    SDIO->MASK|=(1<<1)|(1<<3)|(1<<8)|(1<<5)|(1<<9);  //配置需要的中断 
     SDIO->DCTRL|=1<<3;       //SDIO DMA使能 
     while(((DMA2->ISR&0X2000)==0)&&(TransferEnd==0)&&(TransferError==SD_OK)&&timeout)timeout--;//等待传输完成 
    if(timeout==0)return SD_DATA_TIMEOUT;//超时
    if(TransferError!=SD_OK)errorstatus=TransferError;  
    }   
   return errorstatus; 
}
//SD卡读取多个块 
//buf:读数据缓存区
//addr:读取地址
//blksize:块大小
//nblks:要读取的块数
//返回值:错误状态
__align(4) u32 *tempbuff;
SD_Error SD_ReadMultiBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
{
    SD_Error errorstatus=SD_OK;
  u8 power;
     u32 count=0;
  u32 timeout=SDIO_DATATIMEOUT;  
  tempbuff=(u32*)buf;//转换为u32指针
  
    SDIO->DCTRL=0x0;    //数据控制寄存器清零(关DMA)   
  if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)//大容量卡
  {
    blksize=512;
    addr>>=9;
  }  
     SDIO_Send_Data_Cfg(SD_DATATIMEOUT,0,0,0);  //清除DPSM状态机配置
  if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
  if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
  {
    power=convert_from_bytes_to_power_of_two(blksize);      
    SDIO_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);  //发送CMD16+设置数据长度为blksize,短响应      
    errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);  //等待R1响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误   
  }else return SD_INVALID_PARAMETER;    
  if(nblks>1)                      //多块读  
  {                      
       if(nblks*blksize>SD_MAX_DATA_LENGTH)return SD_INVALID_PARAMETER;//判断是否超过最大接收长度
    SDIO_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,power,1);//nblks*blksize,512块大小,卡到控制器    
      SDIO_Send_Cmd(SD_CMD_READ_MULT_BLOCK,1,addr);  //发送CMD18+从addr地址出读取数据,短响应      
    errorstatus=CmdResp1Error(SD_CMD_READ_MULT_BLOCK);//等待R1响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误    
     if(DeviceMode==SD_POLLING_MODE)
    {
//      INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
      while(!(SDIO->STA&((1<<5)|(1<<1)|(1<<3)|(1<<8)|(1<<9))))//无上溢/CRC/超时/完成(标志)/起始位错误
      {
        if(SDIO->STA&(1<<15))            //接收区半满,表示至少存了8个字
        {
          for(count=0;count<8;count++)      //循环读取数据
          {
            *(tempbuff+count)=SDIO->FIFO;
          }
          tempbuff+=8;   
          timeout=0X7FFFFF;   //读数据溢出时间
        }else   //处理超时
        {
          if(timeout==0)return SD_DATA_TIMEOUT;
          timeout--;
        }
      }  
      if(SDIO->STA&(1<<3))    //数据超时错误
      {                       
         SDIO->ICR|=1<<3;     //清错误标志
        return SD_DATA_TIMEOUT;
       }else if(SDIO->STA&(1<<1))  //数据块CRC错误
      {
         SDIO->ICR|=1<<1;     //清错误标志
        return SD_DATA_CRC_FAIL;       
      }else if(SDIO->STA&(1<<5))   //接收fifo上溢错误
      {
         SDIO->ICR|=1<<5;     //清错误标志
        return SD_RX_OVERRUN;     
      }else if(SDIO->STA&(1<<9))   //接收起始位错误
      {
         SDIO->ICR|=1<<9;     //清错误标志
        return SD_START_BIT_ERR;     
      }   
      while(SDIO->STA&(1<<21))  //FIFO里面,还存在可用数据
      {
        *tempbuff=SDIO->FIFO;  //循环读取数据
        tempbuff++;
      }
       if(SDIO->STA&(1<<8))    //接收结束
      {
        if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))
        {
          SDIO_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);    //发送CMD12+结束传输      
          errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
          if(errorstatus!=SD_OK)return errorstatus;   
        }
       }
//      INTX_ENABLE();//开启总中断
       SDIO->ICR=0X5FF;       //清除所有标记 
     }else if(DeviceMode==SD_DMA_MODE)
    {
         SD_DMA_Config((u32*)buf,nblks*blksize,0); 
         TransferError=SD_OK;
      StopCondition=1;      //多块读,需要发送停止传输指令 
      TransferEnd=0;        //传输结束标置位，在中断服务置1
      SDIO->MASK|=(1<<1)|(1<<3)|(1<<8)|(1<<5)|(1<<9);  //配置需要的中断 
       SDIO->DCTRL|=1<<3;                 //SDIO DMA使能 
       while(((DMA2->ISR&0X2000)==0)&&timeout)timeout--;//等待传输完成 
      if(timeout==0)return SD_DATA_TIMEOUT;//超时
      while((TransferEnd==0)&&(TransferError==SD_OK)); 
      if(TransferError!=SD_OK)errorstatus=TransferError;     
    }     
    }
  return errorstatus;
}                                            
//SD卡写1个块 
//buf:数据缓存区
//addr:写地址
//blksize:块大小    
//返回值:错误状态
SD_Error SD_WriteBlock(u8 *buf,long long addr,  u16 blksize)
{
  SD_Error errorstatus = SD_OK;
  u8  power=0,cardstate=0;
  u32 timeout=0,bytestransferred=0;
  u32 cardstatus=0,count=0,restwords=0;
  u32  tlen=blksize;            //总长度(字节)
  u32*tempbuff=(u32*)buf;                 
   if(buf==NULL)return SD_INVALID_PARAMETER;//参数错误   
    SDIO->DCTRL=0x0;              //数据控制寄存器清零(关DMA)   
    SDIO_Send_Data_Cfg(SD_DATATIMEOUT,0,0,0);  //清除DPSM状态机配置
  if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
   if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)  //大容量卡
  {
    blksize=512;
    addr>>=9;
  }    
  if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
  {
    power=convert_from_bytes_to_power_of_two(blksize);      
    SDIO_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);  //发送CMD16+设置数据长度为blksize,短响应      
    errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);  //等待R1响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误   
  }else return SD_INVALID_PARAMETER;   
     SDIO_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);  //发送CMD13,查询卡的状态,短响应      
  errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);    //等待R1响应          
  if(errorstatus!=SD_OK)return errorstatus;
  cardstatus=SDIO->RESP1;                            
  timeout=SD_DATATIMEOUT;
     while(((cardstatus&0x00000100)==0)&&(timeout>0))   //检查READY_FOR_DATA位是否置位
  {
    timeout--;
       SDIO_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);//发送CMD13,查询卡的状态,短响应      
    errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);  //等待R1响应          
    if(errorstatus!=SD_OK)return errorstatus;            
    cardstatus=SDIO->RESP1;                            
  }
  if(timeout==0)return SD_ERROR;
     SDIO_Send_Cmd(SD_CMD_WRITE_SINGLE_BLOCK,1,addr);  //发送CMD24,写单块指令,短响应      
  errorstatus=CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);//等待R1响应          
  if(errorstatus!=SD_OK)return errorstatus;       
  StopCondition=0;                  //单块写,不需要发送停止传输指令 
   SDIO_Send_Data_Cfg(SD_DATATIMEOUT,blksize,power,0);  //blksize, 控制器到卡    
  timeout=SDIO_DATATIMEOUT;
  if (DeviceMode == SD_POLLING_MODE)
  {
//    INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
    while(!(SDIO->STA&((1<<10)|(1<<4)|(1<<1)|(1<<3)|(1<<9))))//数据块发送成功/下溢/CRC/超时/起始位错误
    {
      if(SDIO->STA&(1<<14))              //发送区半空,表示至少存了8个字
      {
        if((tlen-bytestransferred)<SD_HALFFIFOBYTES)//不够32字节了
        {
          restwords=((tlen-bytestransferred)%4==0)?((tlen-bytestransferred)/4):((tlen-bytestransferred)/4+1);
          
          for(count=0;count<restwords;count++,tempbuff++,bytestransferred+=4)
          {
            SDIO->FIFO=*tempbuff;
          }
        }else
        {
          for(count=0;count<8;count++)
          {
            SDIO->FIFO=*(tempbuff+count);
          }
          tempbuff+=8;
          bytestransferred+=32;
        }
        timeout=0X3FFFFFFF;  //写数据溢出时间
      }else
      {
        if(timeout==0)return SD_DATA_TIMEOUT;
        timeout--;
      }
    } 
    if(SDIO->STA&(1<<3))    //数据超时错误
    {                       
       SDIO->ICR|=1<<3;     //清错误标志
      return SD_DATA_TIMEOUT;
     }else if(SDIO->STA&(1<<1))  //数据块CRC错误
    {
       SDIO->ICR|=1<<1;     //清错误标志
      return SD_DATA_CRC_FAIL;       
    }else if(SDIO->STA&(1<<4))   //接收fifo下溢错误
    {
       SDIO->ICR|=1<<4;     //清错误标志
      return SD_TX_UNDERRUN;     
    }else if(SDIO->STA&(1<<9))   //接收起始位错误
    {
       SDIO->ICR|=1<<9;     //清错误标志
      return SD_START_BIT_ERR;     
    }   
//    INTX_ENABLE();//开启总中断
    SDIO->ICR=0X5FF;       //清除所有标记    
  }else if(DeviceMode==SD_DMA_MODE)
  {
    SD_DMA_Config((u32*)buf,blksize,1);//SDIO DMA配置
       TransferError=SD_OK;
    StopCondition=0;      //单块写,不需要发送停止传输指令 
    TransferEnd=0;        //传输结束标置位，在中断服务置1
    SDIO->MASK|=(1<<1)|(1<<3)|(1<<8)|(1<<4)|(1<<9);  //配置产生数据接收完成中断
      SDIO->DCTRL|=1<<3;                //SDIO DMA使能.  
     while(((DMA2->ISR&0X2000)==0)&&timeout)timeout--;//等待传输完成 
    if(timeout==0)
    {
        SD_Init();             //重新初始化SD卡,可以解决写入死机的问题
      return SD_DATA_TIMEOUT;      //超时   
     }
    timeout=SDIO_DATATIMEOUT;
    while((TransferEnd==0)&&(TransferError==SD_OK)&&timeout)timeout--;
     if(timeout==0)return SD_DATA_TIMEOUT;      //超时   
      if(TransferError!=SD_OK)return TransferError;
   }  
   SDIO->ICR=0X5FF;       //清除所有标记
   errorstatus=IsCardProgramming(&cardstate);
   while((errorstatus==SD_OK)&&((cardstate==SD_CARD_PROGRAMMING)||(cardstate==SD_CARD_RECEIVING)))
  {
    errorstatus=IsCardProgramming(&cardstate);
  }   
  return errorstatus;
}
//SD卡写多个块 
//buf:数据缓存区
//addr:写地址
//blksize:块大小
//nblks:要写入的块数
//返回值:错误状态                           
SD_Error SD_WriteMultiBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
{
  SD_Error errorstatus = SD_OK;
  u8  power = 0, cardstate = 0;
  u32 timeout=0,bytestransferred=0;
  u32 count = 0, restwords = 0;
  u32 tlen=nblks*blksize;        //总长度(字节)
  u32 *tempbuff = (u32*)buf;  
    if(buf==NULL)return SD_INVALID_PARAMETER; //参数错误  
    SDIO->DCTRL=0x0;              //数据控制寄存器清零(关DMA)   
    SDIO_Send_Data_Cfg(SD_DATATIMEOUT,0,0,0);  //清除DPSM状态机配置
  if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
   if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)//大容量卡
  {
    blksize=512;
    addr>>=9;
  }    
  if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
  {
    power=convert_from_bytes_to_power_of_two(blksize);      
    SDIO_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);  //发送CMD16+设置数据长度为blksize,短响应      
    errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);  //等待R1响应   
    if(errorstatus!=SD_OK)return errorstatus;     //响应错误   
  }else return SD_INVALID_PARAMETER;   
  if(nblks>1)
  {            
    if(nblks*blksize>SD_MAX_DATA_LENGTH)return SD_INVALID_PARAMETER;   
       if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))
      {
      //提高性能
          SDIO_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16);  //发送ACMD55,短响应      
      errorstatus=CmdResp1Error(SD_CMD_APP_CMD);    //等待R1响应          
      if(errorstatus!=SD_OK)return errorstatus;            
          SDIO_Send_Cmd(SD_CMD_SET_BLOCK_COUNT,1,nblks);  //发送CMD23,设置块数量,短响应      
      errorstatus=CmdResp1Error(SD_CMD_SET_BLOCK_COUNT);//等待R1响应          
      if(errorstatus!=SD_OK)return errorstatus;            
    } 
    SDIO_Send_Cmd(SD_CMD_WRITE_MULT_BLOCK,1,addr);    //发送CMD25,多块写指令,短响应      
    errorstatus=CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK);  //等待R1响应          
    if(errorstatus!=SD_OK)return errorstatus;
      SDIO_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,power,0);//blksize, 控制器到卡  
    if(DeviceMode==SD_POLLING_MODE)
      {
      timeout=SDIO_DATATIMEOUT;
//      INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)
      while(!(SDIO->STA&((1<<4)|(1<<1)|(1<<8)|(1<<3)|(1<<9))))//下溢/CRC/数据结束/超时/起始位错误
      {
        if(SDIO->STA&(1<<14))              //发送区半空,表示至少存了8字(32字节)
        {    
          if((tlen-bytestransferred)<SD_HALFFIFOBYTES)//不够32字节了
          {
            restwords=((tlen-bytestransferred)%4==0)?((tlen-bytestransferred)/4):((tlen-bytestransferred)/4+1);
            for(count=0;count<restwords;count++,tempbuff++,bytestransferred+=4)
            {
              SDIO->FIFO=*tempbuff;
            }
          }else                     //发送区半空,可以发送至少8字(32字节)数据
          {
            for(count=0;count<SD_HALFFIFO;count++)
            {
              SDIO->FIFO=*(tempbuff+count);
            }
            tempbuff+=SD_HALFFIFO;
            bytestransferred+=SD_HALFFIFOBYTES;
          }
          timeout=0X3FFFFFFF;  //写数据溢出时间
        }else
        {
          if(timeout==0)return SD_DATA_TIMEOUT; 
          timeout--;
        }
      } 
      if(SDIO->STA&(1<<3))    //数据超时错误
      {                       
         SDIO->ICR|=1<<3;     //清错误标志
        return SD_DATA_TIMEOUT;
       }else if(SDIO->STA&(1<<1))  //数据块CRC错误
      {
         SDIO->ICR|=1<<1;     //清错误标志
        return SD_DATA_CRC_FAIL;       
      }else if(SDIO->STA&(1<<4))   //接收fifo下溢错误
      {
         SDIO->ICR|=1<<4;     //清错误标志
        return SD_TX_UNDERRUN;     
      }else if(SDIO->STA&(1<<9))   //接收起始位错误
      {
         SDIO->ICR|=1<<9;     //清错误标志
        return SD_START_BIT_ERR;     
      }                          
      if(SDIO->STA&(1<<8))    //发送结束
      {                               
        if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))
        {
          SDIO_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);    //发送CMD12+结束传输      
          errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
          if(errorstatus!=SD_OK)return errorstatus;   
        }
      }
//      INTX_ENABLE();//开启总中断
       SDIO->ICR=0X5FF;       //清除所有标记 
      }else if(DeviceMode==SD_DMA_MODE)
    {
      SD_DMA_Config((u32*)buf,nblks*blksize,1);//SDIO DMA配置
         TransferError=SD_OK;
      StopCondition=1;      //多块写,需要发送停止传输指令 
      TransferEnd=0;        //传输结束标置位，在中断服务置1
      SDIO->MASK|=(1<<1)|(1<<3)|(1<<8)|(1<<4)|(1<<9);  //配置产生数据接收完成中断
        SDIO->DCTRL|=1<<3;                //SDIO DMA使能. 
      timeout=SDIO_DATATIMEOUT;
       while(((DMA2->ISR&0X2000)==0)&&timeout)timeout--;//等待传输完成 
      if(timeout==0)                   //超时
      {                    
          SD_Init();             //重新初始化SD卡,可以解决写入死机的问题
         return SD_DATA_TIMEOUT;      //超时   
       }
      timeout=SDIO_DATATIMEOUT;
      while((TransferEnd==0)&&(TransferError==SD_OK)&&timeout)timeout--;
       if(timeout==0)return SD_DATA_TIMEOUT;      //超时   
       if(TransferError!=SD_OK)return TransferError;   
    }
    }
   SDIO->ICR=0X5FF;       //清除所有标记
   errorstatus=IsCardProgramming(&cardstate);
   while((errorstatus==SD_OK)&&((cardstate==SD_CARD_PROGRAMMING)||(cardstate==SD_CARD_RECEIVING)))
  {
    errorstatus=IsCardProgramming(&cardstate);
  }   
  return errorstatus;     
}
//SDIO中断服务函数      
void SDIO_IRQHandler(void) 
{                      
   SD_ProcessIRQSrc();//处理所有SDIO相关中断
}                                       
//SDIO中断处理函数
//处理SDIO传输过程中的各种中断事务
//返回值:错误代码
SD_Error SD_ProcessIRQSrc(void)
{
  if(SDIO->STA&(1<<8))//接收完成中断
  {   
    if (StopCondition==1)
    {
      SDIO_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);    //发送CMD12,结束传输      
      TransferError=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);
    }else TransferError = SD_OK;  
     SDIO->ICR|=1<<8;//清除完成中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
     TransferEnd = 1;
    return(TransferError);
  }
   if(SDIO->STA&(1<<1))//数据CRC错误
  {
    SDIO->ICR|=1<<1;//清除中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
      TransferError = SD_DATA_CRC_FAIL;
      return(SD_DATA_CRC_FAIL);
  }
   if(SDIO->STA&(1<<3))//数据超时错误
  {
    SDIO->ICR|=1<<3;//清除中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
      TransferError = SD_DATA_TIMEOUT;
      return(SD_DATA_TIMEOUT);
  }
    if(SDIO->STA&(1<<5))//FIFO上溢错误
  {
    SDIO->ICR|=1<<5;//清除中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
      TransferError = SD_RX_OVERRUN;
      return(SD_RX_OVERRUN);
  }
     if(SDIO->STA&(1<<4))//FIFO下溢错误
  {
    SDIO->ICR|=1<<4;//清除中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
      TransferError = SD_TX_UNDERRUN;
      return(SD_TX_UNDERRUN);
  }
  if(SDIO->STA&(1<<9))//起始位错误
  {
    SDIO->ICR|=1<<9;//清除中断标记
    SDIO->MASK&=~((1<<1)|(1<<3)|(1<<8)|(1<<14)|(1<<15)|(1<<4)|(1<<5)|(1<<9));//关闭相关中断
      TransferError = SD_START_BIT_ERR;
      return(SD_START_BIT_ERR);
  }
  return(SD_OK);
}
  
//检查CMD0的执行状态
//返回值:sd卡错误码
SD_Error CmdError(void)
{
  SD_Error errorstatus = SD_OK;
  u32 timeout=SDIO_CMD0TIMEOUT;     
  while(timeout--)
  {
    if(SDIO->STA&(1<<7))break;  //命令已发送(无需响应)   
  }      
  if(timeout==0)return SD_CMD_RSP_TIMEOUT;  
  SDIO->ICR=0X5FF;        //清除标记
  return errorstatus;
}   
//检查R7响应的错误状态
//返回值:sd卡错误码
SD_Error CmdResp7Error(void)
{
  SD_Error errorstatus=SD_OK;
  u32 status;
  u32 timeout=SDIO_CMD0TIMEOUT;
   while(timeout--)
  {
    status=SDIO->STA;
    if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)  
  }
   if((timeout==0)||(status&(1<<2)))  //响应超时
  {                                            
    errorstatus=SD_CMD_RSP_TIMEOUT;  //当前卡不是2.0兼容卡,或者不支持设定的电压范围
    SDIO->ICR|=1<<2;        //清除命令响应超时标志
    return errorstatus;
  }   
  if(status&1<<6)            //成功接收到响应
  {                   
    errorstatus=SD_OK;
    SDIO->ICR|=1<<6;        //清除响应标志
   }
  return errorstatus;
}     
//检查R1响应的错误状态
//cmd:当前命令
//返回值:sd卡错误码
SD_Error CmdResp1Error(u8 cmd)
{    
     u32 status; 
  while(1)
  {
    status=SDIO->STA;
    if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
  } 
  if(status&(1<<2))          //响应超时
  {                                            
     SDIO->ICR=1<<2;          //清除命令响应超时标志
    return SD_CMD_RSP_TIMEOUT;
  }  
   if(status&(1<<0))          //CRC错误
  {                                            
     SDIO->ICR=1<<0;          //清除标志
    return SD_CMD_CRC_FAIL;
  }    
  if(SDIO->RESPCMD!=cmd)return SD_ILLEGAL_CMD;//命令不匹配 
    SDIO->ICR=0X5FF;           //清除标记
  return (SD_Error)(SDIO->RESP1&SD_OCR_ERRORBITS);//返回卡响应
}
//检查R3响应的错误状态
//返回值:错误状态
SD_Error CmdResp3Error(void)
{
  u32 status;             
   while(1)
  {
    status=SDIO->STA;
    if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)  
  }
   if(status&(1<<2))          //响应超时
  {                       
    SDIO->ICR|=1<<2;        //清除命令响应超时标志
    return SD_CMD_RSP_TIMEOUT;
  }   
     SDIO->ICR=0X5FF;           //清除标记
   return SD_OK;                  
}
//检查R2响应的错误状态
//返回值:错误状态
SD_Error CmdResp2Error(void)
{
  SD_Error errorstatus=SD_OK;
  u32 status;
  u32 timeout=SDIO_CMD0TIMEOUT;
   while(timeout--)
  {
    status=SDIO->STA;
    if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)  
  }
    if((timeout==0)||(status&(1<<2)))  //响应超时
  {                                            
    errorstatus=SD_CMD_RSP_TIMEOUT; 
    SDIO->ICR|=1<<2;        //清除命令响应超时标志
    return errorstatus;
  }   
  if(status&1<<0)            //CRC错误
  {                   
    errorstatus=SD_CMD_CRC_FAIL;
    SDIO->ICR|=1<<0;        //清除响应标志
   }
  SDIO->ICR=0X5FF;           //清除标记
   return errorstatus;                         
} 
//检查R6响应的错误状态
//cmd:之前发送的命令
//prca:卡返回的RCA地址
//返回值:错误状态
SD_Error CmdResp6Error(u8 cmd,u16*prca)
{
  SD_Error errorstatus=SD_OK;
  u32 status;              
  u32 rspr1;
   while(1)
  {
    status=SDIO->STA;
    if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)  
  }
  if(status&(1<<2))          //响应超时
  {                                            
     SDIO->ICR|=1<<2;        //清除命令响应超时标志
    return SD_CMD_RSP_TIMEOUT;
  }      
  if(status&1<<0)            //CRC错误
  {                   
    SDIO->ICR|=1<<0;        //清除响应标志
     return SD_CMD_CRC_FAIL;
  }
  if(SDIO->RESPCMD!=cmd)        //判断是否响应cmd命令
  {
     return SD_ILLEGAL_CMD;     
  }      
  SDIO->ICR=0X5FF;           //清除所有标记
  rspr1=SDIO->RESP1;          //得到响应    
  if(SD_ALLZERO==(rspr1&(SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED)))
  {
    *prca=(u16)(rspr1>>16);      //右移16位得到,rca
    return errorstatus;
  }
     if(rspr1&SD_R6_GENERAL_UNKNOWN_ERROR)return SD_GENERAL_UNKNOWN_ERROR;
     if(rspr1&SD_R6_ILLEGAL_CMD)return SD_ILLEGAL_CMD;
     if(rspr1&SD_R6_COM_CRC_FAILED)return SD_COM_CRC_FAILED;
  return errorstatus;
}

//SDIO使能宽总线模式
//enx:0,不使能;1,使能;
//返回值:错误状态
SD_Error SDEnWideBus(u8 enx)
{
  SD_Error errorstatus = SD_OK;
   u32 scr[2]={0,0};
  u8 arg=0X00;
  if(enx)arg=0X02;
  else arg=0X00;
   if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//SD卡处于LOCKED状态        
   errorstatus=FindSCR(RCA,scr);            //得到SCR寄存器数据
   if(errorstatus!=SD_OK)return errorstatus;
  if((scr[1]&SD_WIDE_BUS_SUPPORT)!=SD_ALLZERO)    //支持宽总线
  {
     SDIO_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16);  //发送CMD55+RCA,短响应                        
     errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
     if(errorstatus!=SD_OK)return errorstatus; 
     SDIO_Send_Cmd(SD_CMD_APP_SD_SET_BUSWIDTH,1,arg);//发送ACMD6,短响应,参数:10,4位;00,1位.                        
    errorstatus=CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH);
    return errorstatus;
  }else return SD_REQUEST_NOT_APPLICABLE;        //不支持宽总线设置    
}                           
//检查卡是否正在执行写操作
//pstatus:当前状态.
//返回值:错误代码
SD_Error IsCardProgramming(u8 *pstatus)
{
   vu32 respR1 = 0, status = 0; 
    SDIO_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);    //发送CMD13      
    status=SDIO->STA;
  while(!(status&((1<<0)|(1<<6)|(1<<2))))status=SDIO->STA;//等待操作完成
     if(status&(1<<0))      //CRC检测失败
  {
    SDIO->ICR|=1<<0;    //清除错误标记
    return SD_CMD_CRC_FAIL;
  }
     if(status&(1<<2))      //命令超时 
  {
    SDIO->ICR|=1<<2;    //清除错误标记
    return SD_CMD_RSP_TIMEOUT;
  }
   if(SDIO->RESPCMD!=SD_CMD_SEND_STATUS)return SD_ILLEGAL_CMD;
  SDIO->ICR=0X5FF;       //清除所有标记
  respR1=SDIO->RESP1;
  *pstatus=(u8)((respR1>>9)&0x0000000F);
  return SD_OK;
}
//读取当前卡状态
//pcardstatus:卡状态
//返回值:错误代码
SD_Error SD_SendStatus(u32 *pcardstatus)
{
  SD_Error errorstatus = SD_OK;
  if(pcardstatus==NULL)
  {
    errorstatus=SD_INVALID_PARAMETER;
    return errorstatus;
  }
   SDIO_Send_Cmd(SD_CMD_SEND_STATUS,1,RCA<<16);  //发送CMD13,短响应     
  errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);  //查询响应状态 
  if(errorstatus!=SD_OK)return errorstatus;
  *pcardstatus=SDIO->RESP1;//读取响应值
  return errorstatus;
} 
//返回SD卡的状态
//返回值:SD卡状态
SDCardState SD_GetState(void)
{
  u32 resp1=0;
  if(SD_SendStatus(&resp1)!=SD_OK)return SD_CARD_ERROR;
  else return (SDCardState)((resp1>>9) & 0x0F);
}
//查找SD卡的SCR寄存器值
//rca:卡相对地址
//pscr:数据缓存区(存储SCR内容)
//返回值:错误状态       
SD_Error FindSCR(u16 rca,u32 *pscr)
{ 
  u32 index = 0; 
  SD_Error errorstatus = SD_OK;
  u32 tempscr[2]={0,0};  
   SDIO_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,8);      //发送CMD16,短响应,设置Block Size为8字节                        
   errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);
   if(errorstatus!=SD_OK)return errorstatus;      
    SDIO_Send_Cmd(SD_CMD_APP_CMD,1,(u32)rca<<16);  //发送CMD55,短响应                     
   errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
   if(errorstatus!=SD_OK)return errorstatus;
  SDIO_Send_Data_Cfg(SD_DATATIMEOUT,8,3,1);    //8个字节长度,block为8字节,SD卡到SDIO.
     SDIO_Send_Cmd(SD_CMD_SD_APP_SEND_SCR,1,0);    //发送ACMD51,短响应,参数为0                        
   errorstatus=CmdResp1Error(SD_CMD_SD_APP_SEND_SCR);
   if(errorstatus!=SD_OK)return errorstatus;                 
   while(!(SDIO->STA&(SDIO_FLAG_RXOVERR|SDIO_FLAG_DCRCFAIL|SDIO_FLAG_DTIMEOUT|SDIO_FLAG_DBCKEND|SDIO_FLAG_STBITERR)))
  { 
    if(SDIO->STA&(1<<21))//接收FIFO数据可用
    {
      *(tempscr+index)=SDIO->FIFO;  //读取FIFO内容
      index++;
      if(index>=2)break;
    }
  }
   if(SDIO->STA&(1<<3))    //接收数据超时
  {                     
     SDIO->ICR|=1<<3;    //清除标记
    return SD_DATA_TIMEOUT;
  }
  else if(SDIO->STA&(1<<1))  //已发送/接收的数据块CRC校验错误
  {
     SDIO->ICR|=1<<1;    //清除标记
    return SD_DATA_CRC_FAIL;   
  }
  else if(SDIO->STA&(1<<5))  //接收FIFO溢出
  {
     SDIO->ICR|=1<<5;    //清除标记
    return SD_RX_OVERRUN;        
  }
  else if(SDIO->STA&(1<<9))  //起始位检测错误
  {
     SDIO->ICR|=1<<9;    //清除标记
    return SD_START_BIT_ERR;    
  }
     SDIO->ICR=0X5FF;       //清除标记   
  //把数据顺序按8位为单位倒过来.     
  *(pscr+1)=((tempscr[0]&SD_0TO7BITS)<<24)|((tempscr[0]&SD_8TO15BITS)<<8)|((tempscr[0]&SD_16TO23BITS)>>8)|((tempscr[0]&SD_24TO31BITS)>>24);
  *(pscr)=((tempscr[1]&SD_0TO7BITS)<<24)|((tempscr[1]&SD_8TO15BITS)<<8)|((tempscr[1]&SD_16TO23BITS)>>8)|((tempscr[1]&SD_24TO31BITS)>>24);
   return errorstatus;
}
//得到NumberOfBytes以2为底的指数.
//NumberOfBytes:字节数.
//返回值:以2为底的指数值
u8 convert_from_bytes_to_power_of_two(u16 NumberOfBytes)
{
  u8 count=0;
  while(NumberOfBytes!=1)
  {
    NumberOfBytes>>=1;
    count++;
  }
  return count;
}    
//配置SDIO DMA  
//mbuf:存储器地址
//bufsize:传输数据量
//dir:方向;1,存储器-->SDIO(写数据);0,SDIO-->存储器(读数据);
void SD_DMA_Config(u32*mbuf,u32 bufsize,u8 dir)
{     
   DMA2->IFCR|=(0XF<<12);        //清除DMA2通道4的各种标记
   DMA2_Channel4->CCR&=~(1<<0);    //关闭DMA 通道4
    DMA2_Channel4->CCR&=~(0X7FF<<4);  //清除之前的设置,DIR,CIRC,PINC,MINC,PSIZE,MSIZE,PL,MEM2MEM
   DMA2_Channel4->CCR|=dir<<4;      //从存储器读   
  DMA2_Channel4->CCR|=0<<5;        //普通模式
  DMA2_Channel4->CCR|=0<<6;       //外设地址非增量模式
  DMA2_Channel4->CCR|=1<<7;        //存储器增量模式
  DMA2_Channel4->CCR|=2<<8;        //外设数据宽度为32位
  DMA2_Channel4->CCR|=2<<10;       //存储器数据宽度32位
  DMA2_Channel4->CCR|=2<<12;       //高优先级    
    DMA2_Channel4->CNDTR=bufsize/4;     //DMA2,传输数据量    
   DMA2_Channel4->CPAR=(u32)&SDIO->FIFO;//DMA2 外设地址 
  DMA2_Channel4->CMAR=(u32)mbuf;     //DMA2,存储器地址
   DMA2_Channel4->CCR|=1<<0;       //开启DMA通道
}   
//读SD卡
//buf:读数据缓存区
//sector:扇区地址
//cnt:扇区个数  
//返回值:错误状态;0,正常;其他,错误代码;                   
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
  u8 sta=SD_OK;
  long long lsector=sector;
  u8 n;
  lsector<<=9;
  if((u32)buf%4!=0)
  {
     for(n=0;n<cnt;n++)
    {
       sta=SD_ReadBlock(SDIO_DATA_BUFFER,lsector+512*n,512);//单个sector的读操作
      memcpy(buf,SDIO_DATA_BUFFER,512);
      buf+=512;
    } 
  }else
  {
    if(cnt==1)sta=SD_ReadBlock(buf,lsector,512);      //单个sector的读操作
    else sta=SD_ReadMultiBlocks(buf,lsector,512,cnt);//多个sector  
  }
  return sta;
}
//写SD卡
//buf:写数据缓存区
//sector:扇区地址
//cnt:扇区个数  
//返回值:错误状态;0,正常;其他,错误代码;  
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
  u8 sta=SD_OK;
  u8 n;
  long long lsector=sector;
  lsector<<=9;
  if((u32)buf%4!=0)
  {
     for(n=0;n<cnt;n++)
    {
      memcpy(SDIO_DATA_BUFFER,buf,512);
       sta=SD_WriteBlock(SDIO_DATA_BUFFER,lsector+512*n,512);//单个sector的写操作
      buf+=512;
    } 
  }else
  {
    if(cnt==1)sta=SD_WriteBlock(buf,lsector,512);      //单个sector的写操作
    else sta=SD_WriteMultiBlocks(buf,lsector,512,cnt);  //多个sector  
  }
  return sta;
}







